import inspect
from pydantic import conint

from common.base.base_api import BaseApi
from services.ad936x.schemas.configs import DoubleConfig, SingleConfig, DoubleFrequency, SingleFrequency, DoubleGain, \
    SingleGain, SingleAttenuation, DoubleAttenuation
from settings import settings


class Ad936xApi(BaseApi):
    __slots__ = []

    def __init__(self):
        super(Ad936xApi, self).__init__(request_queue_uuid=settings.AD936X_REQUEST_QUEUE)

    async def direct_write_bandwidth(self, index: int, bw: int):
        return await self.send_rpc_request_message(inspect.currentframe().f_code.co_name, {'index': index, 'bw': bw})

    async def digital_tune(self, index):
        return await self.send_rpc_request_message(inspect.currentframe().f_code.co_name, {'index': index})

    async def digital_tune_all(self):
        return await self.send_rpc_request_message(inspect.currentframe().f_code.co_name)

    async def configure(self, index: conint(ge=0, lt=settings.AD936X_NUMBER), config: DoubleConfig | SingleConfig
                  ) -> bool | None:
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
            {
                'index': index,
                'config': config
            }
        )

    async def set_center_frequency(self, index: conint(ge=0, lt=settings.AD936X_NUMBER),
                             config: DoubleFrequency | SingleFrequency) -> bool | None:
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
            {
                'index': index,
                'config': config
            }
        )

    async def set_gain(self, index: conint(ge=0, lt=settings.AD936X_NUMBER), config: DoubleGain | SingleGain
                 ) -> bool | None:
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
            {
                'index': index,
                'config': config
            }
        )

    async def set_attenuation(self, index: conint(ge=0, lt=settings.AD936X_NUMBER),
                        config: DoubleAttenuation | SingleAttenuation) -> bool | None:
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
            {
                'index': index,
                'config': config
            }
        )

    async def get_all_configs(self) -> list[DoubleConfig | SingleConfig] | None:
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
            handle_result=lambda result: [
                DoubleConfig(**res) if res['double'] else SingleConfig(**res)
                for res in result
            ]
        )

    async def get_config(self, index: conint(ge=0, lt=settings.AD936X_NUMBER)
                   ) -> DoubleConfig | SingleConfig | None:
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
            {'index': index},
            handle_result=lambda result: DoubleConfig(**result) if result['double'] else SingleConfig(**result)
        )

    async def get_statuses(self) -> list[bool]:
        return await self.send_rpc_request_message(inspect.currentframe().f_code.co_name)

    async def get_real_uldl(self, index: int) -> tuple[float, float] | None:
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
            {
                'index': index,
            }
        )

    async def set_night_digital_tune(self, night_digital_tune: bool):
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
            {
                'night_digital_tune': night_digital_tune
            }
        )

    async def get_night_digital_tune(self) -> bool:
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
        )

    async def set_digital_tune_range(self, index: int, digital_tune_range: tuple[int, int, int, int]):
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
            {
                'index': index,
                'digital_tune_range': digital_tune_range
            }
        )

    async def get_digital_tune_range(self, index: int) -> tuple[int, int, int, int]:
        return await self.send_rpc_request_message(
            inspect.currentframe().f_code.co_name,
            {
                'index': index,
            }
        )